Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support uint64 for case statement operands #820

Merged
merged 7 commits into from
Jul 31, 2023

Conversation

zerbina
Copy link
Collaborator

@zerbina zerbina commented Jul 30, 2023

Summary

Allow uint64 values to be used as case-statement operands and fix
multiple compiler crashes with uint of-branch labels outside the
int64 range. Previously, trying to use a uint64 value with case
statements resulted in a "selector must be of an ordinal type" error.

  • uint64 values can now be used as case-statement operands (outside
    of objects)
  • literal set constructors in of-branches don't crash the compiler
    when the range of the element value crosses high(int64)
  • when using the C or JS backend, .. ranges in of-branches don't
    crash the compiler when the lower bound is less-than-or-equal to,
    and the upper bound greater than high(int64)
  • when using the JS backend, unsigned integer literals beyond
    high(int64) are not treated as -1 - high(uint64) - value
    anymore

Details

uint64 being disallowed as case-statement operands seems to have
been a leftover from when uint64 was not considered an ordinal type.
Since it is considered an ordinal type now, not allowing it there is
inconsistent.

The compiler crashes were all caused by signed integer overflow
defects. All integer values are stored as BiggestInt (signed) in
PNode, even unsigned values. Prior to working with them, they have to
be either casted to an unsigned integer (in case the node represents
an unsigned value) or turned into an Int128 value via getOrdValue/
getInt (both which take care of properly reinterpreting the value).

This was missing in toTreeSet, which is called when removing
duplicate elements from set literals used as of-branch labels.
Instead of turning the sets' lower bound (firstOrd) into a signed
integer, the value is now kept as an Int128, fixing the overflow
defect.

The other problems where with the C and JavaScript code generators,
both which were using the nodes intVal directly when iterating over
nkRanges -- they now use Int128 values. In order to not having
to create a temporary PNode, the integer-literal rendering logic
for both code generators is moved to standalone procedures that take
an Int128 value directly (which for the JavaScript backend fixes
large unsigned values being inverted).

Instead of inferring the integer type from the node kind, cgen now
requires all integer literals to be typed, which is preparation for the
code-generator IR.

When using the VM backend, of-branches with ranges crossing
high(int64) still don't work correctly, as the VM uses signed
integers for the comparisons. Fixing this requires a larger rethinking
of the VM's case statement support, and it is thus left as is for now.

zerbina added 7 commits July 30, 2023 15:47
The `uint64` is considered an ordinal type by `isOrdinal`, and not
supporting it here seems like an oversight.
Keep the `firstOrd` result as an `Int128`, fixing the compiler crashing
with integer overflow defects when the `first` + element value is
outside the `int64` range.

In addition, use `let` where it makes sense, and replace appending to
the `nkRange` node with setting the elements directly.
Move the logic into a standalone procedure, in preparation for the
following fix. In addition, integer-literal nodes reaching the C code
generator are now required to be typed.
For generating code for `of`-branches, don't operate with the signed
`intVal` values, but turn them into `Int128` values first.

When using C compilers that don't support case ranges, this fixes the
compiler crashing with overflow defects.
* move code-generation for integer literals into a standalone procedure
* same as with the C code generator, use `Int128` values when iterating
  over the range
Compiling it doesn't crash the compiler anymore, at least.
@zerbina zerbina added bug Something isn't working enhancement New feature or request compiler/sem Related to semantic-analysis system of the compiler compiler/backend Related to backend system of the compiler labels Jul 30, 2023
@saem
Copy link
Collaborator

saem commented Jul 31, 2023

/merge

@github-actions
Copy link

Merge requested by: @saem

Contents after the first section break of the PR description has been removed and preserved below:


Notes for Reviewers

@chore-runner chore-runner bot added this pull request to the merge queue Jul 31, 2023
Merged via the queue into nim-works:devel with commit b529dcf Jul 31, 2023
@zerbina zerbina deleted the support-uint64-for-case-stmt branch July 31, 2023 18:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working compiler/backend Related to backend system of the compiler compiler/sem Related to semantic-analysis system of the compiler enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants